package webapp.mvc.controllers;

import cn.apiclub.captcha.Captcha;
import cn.apiclub.captcha.gimpy.BlockGimpyRenderer;
import cn.apiclub.captcha.servlet.CaptchaServletUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import webapp.mvc.controllers.forms.SimpleResponse;
import webapp.mvc.models.CaptchaRequestEntity;
import webapp.mvc.services.ICaptchaService;
import webapp.mvc.utils.StaticTextProducer;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Calendar;
import java.util.Date;

@Controller
@RequestMapping("/captcha")
public class CaptchaController {
    private static final Logger LOG = LoggerFactory.getLogger(CaptchaController.class);

    @Autowired
    private ICaptchaService captchaService;

    @RequestMapping("")
    public
    @ResponseBody
    String index() {
        return "Hello, this is a very simple captcha service";
    }

    @RequestMapping("/requestCaptcha")
    public
    @ResponseBody
    String requestCaptcha() {
        CaptchaRequestEntity captchaRequest = captchaService.newCaptchaRequest();
        JSONObject captchaRequestJsonObject = new JSONObject();
        captchaRequestJsonObject.put("id", captchaRequest.getId());
        captchaRequestJsonObject.put("answer", captchaRequest.getAnswer());
        captchaRequestJsonObject.put("expireSeconds", captchaRequest.getExpireSeconds());
        String captchaRequestJson = JSON.toJSONString(captchaRequestJsonObject);
        return SimpleResponse.ok(captchaRequestJson).toJSON();
    }

    @RequestMapping("/request_for_current_user")
    public
    @ResponseBody
    String requestCaptchaForCurrentUser(HttpServletRequest request) {
        HttpSession session = request.getSession(true);
        CaptchaRequestEntity captchaRequest = captchaService.newCaptchaRequest();
        session.setAttribute("captchaId", captchaRequest.getId());
        return SimpleResponse.ok(captchaRequest.getId()).toJSON();
    }

    @RequestMapping("/view/{id}")
    public
    @ResponseBody
    Object view(HttpServletRequest request, HttpServletResponse response, @PathVariable String id) {
        CaptchaRequestEntity captchaRequest = captchaService.findById(id);
        if (captchaRequest == null) {
            return SimpleResponse.fail(String.format("Can't find captcha request #%s", id)).toJSON();
        }
        String text = captchaRequest.getAnswer();
        char[] chars = text.toCharArray();
        String finalText = "";
        for (char c : chars) {
            finalText += "" + c + "  ";
        }
        Captcha captcha = new Captcha.Builder(120, 48)
                .addText(new StaticTextProducer(finalText))
                .gimp(new BlockGimpyRenderer(4))
                .build();
//        LOG.info("answer: " + captcha.getAnswer());
        CaptchaServletUtil.writeImage(response, captcha.getImage());
        return null;
    }

    @RequestMapping(value = "/validate", method = {RequestMethod.POST, RequestMethod.GET})
    public
    @ResponseBody
    String validate(HttpServletRequest request) {
        String id = request.getParameter("id");
        String answer = request.getParameter("answer");
        CaptchaRequestEntity captchaRequest = captchaService.findById(id);
        if (captchaRequest == null) {
            return SimpleResponse.fail(String.format("Can't find captcha request #%s", id)).toJSON();
        }
        Date now = new Date();
        Date expiresTime = captchaRequest.getCreatedTime();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(expiresTime);
        calendar.add(Calendar.SECOND, captchaRequest.getExpireSeconds());
        expiresTime = calendar.getTime();
        if (now.after(expiresTime)) {
            return SimpleResponse.fail("The captcha expired!").toJSON();
        }
        boolean result = captchaRequest.getAnswer().equalsIgnoreCase(answer);
        return SimpleResponse.ok(result).toJSON();
    }
}
